using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Input;
using Microsoft.Win32;
using System.Diagnostics.Contracts;
using Konst3d.Efficiency;
using Konst3d.Efficiency.Suite;
using Konst3d.Efficiency.Suite.SparsedBinary;
using System.Windows;

namespace PEM
{
    internal partial class MainWindowViewModel // SuiteCommands
    {
        public class OpenSuiteCommand : ICommand
        {
            #region Constructor

            public OpenSuiteCommand(MainWindowViewModel model)
            {
                Contract.Requires(model != null);
                _model = model;
            }

            #endregion // Constructor

            #region ICommand Members

            public bool CanExecute(object parameter)
            {
                return true;
            }

            public event EventHandler CanExecuteChanged;

            public void Execute(object parameter)
            {
                _model.OpenSuite();
            }

            #endregion

            #region Fields

            private MainWindowViewModel _model;

            #endregion // Fields
        }

        public class CloseSuiteCommand : ICommand
        {
            #region Constructor

            public CloseSuiteCommand(MainWindowViewModel model)
            {
                Contract.Requires(model != null);
                _model = model;

                _model.SuiteClosed += OnSuiteOpenedOrClosed;
                _model.SuiteOpened += OnSuiteOpenedOrClosed;
                _model.SuiteCreated += OnSuiteOpenedOrClosed;
                _model.SuiteDeleted += OnSuiteOpenedOrClosed;
            }

            #endregion // Constructor

            #region ICommand Members

            public bool CanExecute(object parameter)
            {
                return _model.Suite != null;
            }

            public event EventHandler CanExecuteChanged;

            public void Execute(object parameter)
            {
                _model.CloseSuite();
            }

            #endregion

            #region Event Handlers

            private void OnSuiteOpenedOrClosed(MainWindowViewModel sender)
            {
                if (CanExecuteChanged != null)
                {
                    CanExecuteChanged(this, EventArgs.Empty);
                }
            }

            #endregion // Event Handlers

            #region Fields

            private MainWindowViewModel _model;

            #endregion // Fields
        }

        public class CreateSuiteCommand : ICommand
        {
            #region Constructor

            public CreateSuiteCommand(MainWindowViewModel model)
            {
                Contract.Requires(model != null);
                _model = model;
            }

            #endregion // Constructor

            #region ICommand Members

            public bool CanExecute(object parameter)
            {
                return true;
            }

            public event EventHandler CanExecuteChanged;

            public void Execute(object parameter)
            {
                _model.CreateSuite();
            }

            #endregion

            #region Fields

            private MainWindowViewModel _model;

            #endregion // Fields
        }

        public class DeleteSuiteCommand : ICommand
        {
            #region Constructor

            public DeleteSuiteCommand(MainWindowViewModel model)
            {
                Contract.Requires(model != null);
                _model = model;

                _model.SuiteClosed += OnSuiteOpenedOrClosed;
                _model.SuiteOpened += OnSuiteOpenedOrClosed;
                _model.SuiteCreated += OnSuiteOpenedOrClosed;
                _model.SuiteDeleted += OnSuiteOpenedOrClosed;
            }

            #endregion // Constructor

            #region ICommand Members

            public bool CanExecute(object parameter)
            {
                return _model.Suite != null;
            }

            public event EventHandler CanExecuteChanged;

            public void Execute(object parameter)
            {
                _model.DeleteSuite();
            }

            #endregion

            #region Event Handlers

            private void OnSuiteOpenedOrClosed(MainWindowViewModel sender)
            {
                if (CanExecuteChanged != null)
                {
                    CanExecuteChanged(this, EventArgs.Empty);
                }
            }

            #endregion // Event Handlers

            #region Fields

            private MainWindowViewModel _model;

            #endregion // Fields
        }

        public class CommandsCollection
        {
            #region Properties

            public OpenSuiteCommand OpenSuite
            {
                get;
                private set;
            }

            public CloseSuiteCommand CloseSuite
            {
                get;
                private set;
            }

            public CreateSuiteCommand CreateSuite
            {
                get;
                private set;
            }

            public DeleteSuiteCommand DeleteSuite
            {
                get;
                private set;
            }

            #endregion // Properties

            #region Constructor

            public CommandsCollection(MainWindowViewModel model)
            {
                Contract.Requires(model != null);

                OpenSuite = new OpenSuiteCommand(model);
                CloseSuite = new CloseSuiteCommand(model);
                CreateSuite = new CreateSuiteCommand(model);
                DeleteSuite = new DeleteSuiteCommand(model);
            }

            #endregion // Constructor
        }

        public void OpenSuite()
        {
            if (!_openSuiteDialog.ShowDialog() ?? true)
            {
                return;
            }

            if (Suite != null)
            {
                SuiteCommands.Close.Execute(null, null);
            }

            int cryptographicEngineID = SparseBinaryStorage.GetCryptographicEngineID(_openSuiteDialog.FileName);

            Contract.Assert(cryptographicEngineID >= 0 && cryptographicEngineID < _cryptographicEngines.Length);

            string login = String.Empty;
            string password = String.Empty;

            if (SparseBinaryStorage.IsPasswordProtected(_openSuiteDialog.FileName, _cryptographicEngines[cryptographicEngineID]))
            {
                if (_suiteLoginDialog.ShowDialog(_window))
                {
                    login = _suiteLoginDialog.SuiteLogin;
                    password = _suiteLoginDialog.SuitePassword;
                }
                else
                {
                    return;
                }
            }

            Suite = SparseBinaryStorage.Open(_openSuiteDialog.FileName, login, password, _cryptographicEngines[cryptographicEngineID]);

            if (SuiteOpened != null)
            {
                SuiteOpened(this);
            }
        }

        public void CloseSuite()
        {
            if (Suite != null)
            {
                Suite.Dispose();
                Suite = null;

                if (SuiteClosed != null)
                {
                    SuiteClosed(this);
                }
            }
        }

        public void CreateSuite()
        {
            if (_createSuiteDialog.ShowDialog(_window))
            {
                if (Suite != null)
                {
                    CloseSuite();
                }

                Suite = SparseBinaryStorage.Create(_createSuiteDialog.SuiteFileName,
                    true,
                    _createSuiteDialog.SuiteLogin,
                    _createSuiteDialog.SuitePassword,
                    _createSuiteDialog.SuiteCryptographicEngine,
                    _createSuiteDialog.SuiteCryptographicEngineID);

                if (SuiteCreated != null)
                {
                    SuiteCreated(this);
                }
            }
        }

        public void DeleteSuite()
        {
            Contract.Assert(Suite != null);

            if (MessageBox.Show("Are you really wish to delete this suite!") != MessageBoxResult.Yes)
            {
                return;
            }

            Suite.Delete();
            Suite = null;

            if (SuiteDeleted != null)
            {
                SuiteDeleted(this);
            }
        }
    }
}
